package com.w3c.pragmatic.threadpool;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * 自定义线程池
 *
 * @author wangdong
 * @since 2025/3/11 9:31
 */
@Slf4j
@Data
public class CustomerThreadPool {

  // 默认常驻线程数
  private static final int DEFAULT_CORE_POOL_SIZE = 1;
  // 默认最大线程数
  private static final int DEFAULT_MAXIMUM_POOL_SIZE = 3;
  // 默认线程数大于常驻线程数并且存在空闲线程数，空闲时间超过30S,则回收
  private static final long DEFAULT_KEEP_ALIVE_TIME = 30L;
  // 默认阻塞队列大小
  static BlockingQueue<Runnable> DEFAULT_WORK_QUEUE = new LinkedBlockingQueue<>(10);
  // 默认拒绝策略
  private static final RejectedExecutionHandler DEFAULT_HANDLER =
      (r, executor) -> {
        final Thread t = new Thread(r, "Temporary task executor");
        t.start();
      };

  // 常驻线程数
  private int corePoolSize;
  // 最大线程数
  private int maximumPoolSize;
  // 当线程数大于常驻线程数并且存在空闲线程数，空闲时间超过10S,则回收
  private long keepAliveTime;
  // 阻塞队列
  BlockingQueue<Runnable> workQueue;
  // 拒绝策略(核心线程数满 -> 阻塞队列满 -> 最大线程数满 -> 决绝策略)
  private RejectedExecutionHandler handler;

  /** 无参构造器，全部使用默认参数 */
  public CustomerThreadPool() {
    this(DEFAULT_CORE_POOL_SIZE, DEFAULT_MAXIMUM_POOL_SIZE, DEFAULT_WORK_QUEUE);
  }

  /**
   * 构造器
   *
   * @param corePoolSize 常驻线程数
   * @param maximumPoolSize 最大线程数
   * @param workQueue 阻塞队列
   */
  public CustomerThreadPool(
      int corePoolSize, int maximumPoolSize, BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, DEFAULT_KEEP_ALIVE_TIME, workQueue);
  }

  /**
   * 构造器
   *
   * @param corePoolSize 常驻线程数
   * @param maximumPoolSize 最大线程数
   * @param keepAliveTime 空闲等待时间
   * @param workQueue 阻塞队列
   */
  public CustomerThreadPool(
      int corePoolSize,
      int maximumPoolSize,
      long keepAliveTime,
      BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, workQueue, DEFAULT_HANDLER);
  }

  /**
   * 构造器
   *
   * @param corePoolSize 常驻线程数
   * @param maximumPoolSize 最大线程数
   * @param keepAliveTime 空闲等待时间
   * @param workQueue 阻塞队列
   * @param handler 拒绝策略
   */
  public CustomerThreadPool(
      int corePoolSize,
      int maximumPoolSize,
      long keepAliveTime,
      BlockingQueue<Runnable> workQueue,
      RejectedExecutionHandler handler) {
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.keepAliveTime = keepAliveTime;
    this.workQueue = workQueue;
    this.handler = handler;
  }

  // 创建线程池
  public ThreadPoolExecutor createCustomerThreadPool() {
    // 获取cpu核数
    // 至于io密集型还是cpu密集型在于corePoolSize的计算和配置
    // corePoolSize = Runtime.getRuntime().availableProcessors();
    // 返回线程池
    return new ThreadPoolExecutor(
        corePoolSize,
        maximumPoolSize,
        keepAliveTime,
        TimeUnit.SECONDS,
        workQueue,
        Executors.defaultThreadFactory(),
        handler);
  }
}
